import os
import binascii
import fcntl
import socket,struct

con_cache = 200*1024
tapReadLen = 2000
sockReadLen = 65536
udpEffctTime = 5
tcpEffctTime = 60
maxFakeIp = 1000
cupIpInterval = 10
fakeIpEffectTime = 20


con_devMac = '3a:da:0a:78:99:ec'
con_fakeMac = '3a:da:0a:78:99:ed'
con_devMacB = binascii.unhexlify(con_devMac.replace(':',''))
con_fakeMacB = binascii.unhexlify(con_fakeMac.replace(':',''))
con_outEth = 'eno1'
con_gatewayIp = '154.221.22.22'

enableUdpProxy = True
sslocalAddUdp = ('127.0.0.1',4332)
sslocalAdd = ('127.0.0.1',11080)

mydevIp = '192.168.100.1'
mydevIp3 = '192.168.100.'
mydevIpB = socket.inet_aton(mydevIp)

debugIp = '42.51.28.250'
debugIpB = socket.inet_aton(debugIp)


err_begin_len_small = 'err_begin_len_small'
err_arp_len_small = 'err_arp_len_small'
err_arp_eth = 'err_arp_eth'
err_arp_pro = 'err_arp_pro'
err_arp_pro_len = 'err_arp_pro_len'
err_arp_type = 'err_arp_type'
err_eth_type = 'err_eth_type'
err_ipv4_len = 'err_ipv4_len'
err_ipv4_type = 'err_ipv4_type'

ty_arp_request = 1
ty_arp_reply = 2
ty_icmp = 3
ty_udp= 4
ty_tcp= 5
ty_err = 0

def clearDev():
    os.system('ip netns exec a ifconfig |grep mydev:>a.txt')
    f=open('a.txt')
    s = f.readlines()
    for one in s:
        a = one.split()[0]
        if a != 'mydev:':
            cmd = 'ip netns exec a ifconfig %s down '%a[:-1]
            print (cmd)
            os.system(cmd)

def debugPrint(*a,**b):
    print(*a,**b)
    
def getTcpFlags(a):
    l = []
    if a&0x01:
        l.append('Fin')
    if a&0x02:
        l.append('Syn')
    if a&0x04:
        l.append('Reset')
    if a&0x08:
        l.append('Push')
    if a&0x10:
        l.append('Ack')
    return l
                                           
#return type,srcIp,dstIp,flags,code
def checkEth(buf):
    le = len(buf)
    
    if le<14:
        return ty_err,None,None,None,err_begin_len_small    

    if buf[12]==8 and buf[13]==6:
        if le<42:
            return ty_err,None,None,None,err_arp_len_small  
        
        if buf[14]!=0 or buf[15]!=1:
            return ty_err,None,None,None,err_arp_eth 
        
        if buf[16]!=8 or buf[17]!=0:
            return ty_err,None,None,None,err_arp_pro    
        
        if buf[18]!=6 or buf[19]!=4:
            return ty_err,None,None,None,err_arp_pro_len  
        
        if buf[20]==0 and buf[21]==1:
            srcIp = buf[28:32]
            dstIp = buf[38:42]
            return ty_arp_request,srcIp,dstIp,0,''
            
        elif buf[20]==0 and buf[21]==2:
            srcIp = buf[28:32]
            dstIp = buf[38:42]
            return ty_arp_reply,srcIp,dstIp,0,""
        
        else:
            return ty_err,None,None,None,err_arp_type    
                 
    elif buf[12]==0x08 and buf[13]==0: 
        if len(buf)<35:
            return ty_err,None,None,None ,err_ipv4_len
        
        srcIp = buf[26:30]
        dstIp = buf[30:34]
        
        if buf[23]==1:
            return ty_icmp,srcIp,dstIp,0,''
        
        elif buf[23]==6:    
            return ty_tcp,srcIp,dstIp,getTcpFlags(buf[47]),''
        
        elif buf[23]==17:            
            return ty_udp,srcIp,dstIp,0,''
        
        else:
            return ty_err,None,None,None,err_ipv4_type             
             
    else:
        return ty_err,None,None,None,err_eth_type    
        

def openTap(name):
    TUNSETIFF = 0x400454ca
    TUNSETOWNER = TUNSETIFF + 2
    IFF_TUN = 0x0001
    IFF_TAP = 0x0002
    IFF_NO_PI = 0x1000
    tun = open('/dev/net/tun', 'r+b',buffering=0)
    ifr = struct.pack('16sH', name, IFF_TAP | IFF_NO_PI)
    fcntl.ioctl(tun, TUNSETIFF, ifr)
    return tun

def doIproute():
    cmd = 'ip netns exec a arp -i mydev -s %s %s  > /dev/null 2>&1'%(con_gatewayIp,con_fakeMac)
    os.system(cmd)
    cmd = 'ip netns exec a ip route add default via %s dev mydev onlink > /dev/null 2>&1'%(con_gatewayIp)
    os.system(cmd)  
    
def doIproute_noblock():
    cmd = 'nohup ip netns exec a arp -i mydev -s %s %s  > /dev/null 2>&1 &'%(con_gatewayIp,con_fakeMac)
    os.system(cmd)
    cmd = 'nohup ip netns exec a ip route add default via %s dev mydev onlink > /dev/null 2>&1 &'%(con_gatewayIp)
    os.system(cmd) 
    
def ini():
    os.system('ovs-vsctl del-br br0')
    os.system('ovs-vsctl del-br br1')
    os.system('ovs-vsctl del-br br2')
    os.system('ip tuntap del dev tap0 mod tap')
    os.system('ip tuntap del dev tap1 mod tap')
    os.system('ip tuntap del dev tap2 mod tap')
    os.system('ip netns del a')
    os.system('ip netns del a2')
    
    os.system('ovs-vsctl add-br br0')
    os.system('ovs-vsctl add-br br1')
    os.system('ovs-vsctl add-br br2')
    os.system('ip tuntap add dev tap0 mod tap')
    os.system('ip link set tap0 up')   
    os.system('ip tuntap add dev tap1 mod tap')
    os.system('ip link set tap1 up')   
    os.system('ip tuntap add dev tap2 mod tap')
    os.system('ip link set tap2 up')   
    os.system('ip netns add a')
    os.system('ip netns add a2')
    os.system('ip netns exec a ip link set lo up')
    os.system('ip netns exec a2 ip link set lo up')
    
    os.system('ovs-vsctl add-port br0 '+con_outEth)
    os.system('ovs-vsctl add-port br0 tap0')
    os.system('ovs-vsctl add-port br1 tap1')
    os.system('ovs-vsctl add-port br1 mydev -- set Interface mydev type=internal')   
    os.system('ip link set mydev netns a')
    os.system('ip netns exec a ip link set mydev up')
    cmd = 'ip netns exec a ifconfig mydev hw ether %s up'%con_devMac
    os.system(cmd)  
    
    os.system('ovs-vsctl add-port br2 tap2')
    os.system('ovs-vsctl add-port br2 mydev2 -- set Interface mydev2 type=internal')   
    os.system('ip link set mydev2 netns a2')
    os.system('ip netns exec a2 ip link set mydev2 up')
    cmd = 'ip netns exec a2 ifconfig mydev2 hw ether %s up'%con_devMac
    os.system('ip netns exec a2 ifconfig mydev2 %s up'%mydevIp)
    os.system(cmd)
    
    os.system('ip netns exec a iptables -t nat -F')
    os.system('ip netns exec a iptables -t mangle -F')
    os.system('ip netns exec a iptables -t nat -A PREROUTING -p tcp --dport 0:65535 -j REDIRECT --to-port 8080 -i mydev')
    os.system('ip netns exec a iptables -t mangle -N DIVERT')
    os.system('ip netns exec a iptables -t mangle -A PREROUTING -p udp  -j DIVERT')
    os.system('ip netns exec a iptables -t mangle -A DIVERT -j MARK --set-mark 1')
    os.system('ip netns exec a iptables -t mangle -A DIVERT  -p udp --dport 0:65535 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 8081 -i mydev')
    os.system('ip netns exec a iptables -t mangle -A DIVERT -j ACCEPT')
    os.system('ip netns exec a ip rule add fwmark 1 lookup 100')
    os.system('ip netns exec a ip route add local 0.0.0.0/0 dev lo table 100  ') 
